﻿// -----------------------------------------------------------------------
// <copyright file="StringExtensions.cs" company="EPAM Systems">
////Copyright (c) EPAM Systems, 2012. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

namespace MBOP.Helpers.Extensions
{
	#region Usings

	using System;
	using System.Text;

	#endregion

	/// <summary>
	/// Provides extensions for datetime time structure.
	/// </summary>
	public static class DateTimeExtensions
	{
		private struct TimeInterval
		{
			private int _years;
			private int _months;
			private int _days;
			private int _hours;
			private int _minutes;
			private int _seconds;

			public TimeInterval(int years, int months, int days, int hours, int minutes, int seconds)
			{
				_years = years;
				_months = months;
				_days = days;
				_hours = hours;
				_minutes = minutes;
				_seconds = seconds;
			}

			public int Years
			{
				get { return _years; }
			}

			public int Months 
			{
				get { return _months; }
			}

			public int Days
			{
				get { return _days; }
			}

			public int Hours
			{
				get { return _hours; }
			}

			public int Minutes
			{
				get { return _minutes; }
			}

			public int Seconds
			{
				get { return _seconds; }
			}


		}

		#region Constants

		private const int MONTHS_IN_YEAR = 12;

		private const int DAYS_IN_COMMON_YEAR = 365;

		private const int DAYS_IN_LEAP_YEAR = 366;

		private const int SECONDS_IN_MINUTES = 60;

		private const int MINUTES_IN_HOUR = 60;

		private const int HOURS_IN_DAY = 24;

		#endregion

		/// <summary>
		/// Gets the time inteval from current start date to present.
		/// </summary>
		/// <param name="date">The date.</param>
		/// <returns>The time interval string.</returns>
		public static string GetTimeInteval(this DateTime date)
		{
			TimeInterval pastTimeInterval = GetPastTimeInterval(date);

			StringBuilder result = new StringBuilder();

			if (pastTimeInterval.Years > 0)
			{
				result
					.Append(FormatDatePart(pastTimeInterval.Years, "year"))
					.Append(FormatDatePart(pastTimeInterval.Months, "month"))
					.Append(FormatDatePart(pastTimeInterval.Days, "day"));
			}
			else if (pastTimeInterval.Months > 0)
			{
				result
					.Append(FormatDatePart(pastTimeInterval.Months, "month"))
					.Append(FormatDatePart(pastTimeInterval.Days, "day"))
					.Append(FormatDatePart(pastTimeInterval.Hours, "hour"));
			}
			else if (pastTimeInterval.Days > 0)
			{
				result
					.Append(FormatDatePart(pastTimeInterval.Days, "days"))
					.Append(FormatDatePart(pastTimeInterval.Hours, "hour"))
					.Append(FormatDatePart(pastTimeInterval.Minutes, "minute"));
			}
			else
			{
				result
					.Append(FormatDatePart(pastTimeInterval.Hours, "hour"))
					.Append(FormatDatePart(pastTimeInterval.Minutes, "minute"))
					.Append(FormatDatePart(pastTimeInterval.Seconds, "second"));
			}
			
			return result.ToString();
		}

		private static string FormatDatePart(int datePart, string alias)
		{
			string result = string.Empty;

			if (datePart > 0)
			{
				string postfix = (datePart > 1) ? "s" : string.Empty;

				result = string.Format("{0} {1}{2} ", datePart, alias, postfix);
			}

			return result;
		}

		private static TimeInterval GetPastTimeInterval(DateTime date)
		{
			DateTime currentDate = DateTime.Now;

			DateTime endDate;
			DateTime startDate;

			if (date < currentDate)
			{
				endDate = currentDate;
				startDate = date;
			}
			else
			{
				endDate = date;
				startDate = endDate;
			}

			TimeSpan endStartDifference = endDate - startDate;

			DateTime endDateMonth = new DateTime(endDate.Year, endDate.Month, startDate.Day, startDate.Hour, startDate.Minute, startDate.Second);

			TimeSpan endDateMonthDifference;

			int totalMonths = 0;

			if (endDate >= endDateMonth)
			{
				endDateMonthDifference = endDateMonth - startDate;
				totalMonths += endDate.Month - startDate.Month;
			}
			else
			{
				DateTime endDateMonthTmp = endDateMonth;

				endDateMonthDifference = endDateMonthTmp.AddMonths(-1) - startDate;

				totalMonths += endDateMonthTmp.Month - startDate.Month;
			}

			int yearsDifference = endDate.Year - startDate.Year;

			if (yearsDifference != 0 && endDate < endDateMonth)
			{
				yearsDifference--;
			}

			totalMonths += yearsDifference * MONTHS_IN_YEAR;

			TimeSpan spanFromCurrentMonth = endStartDifference - endDateMonthDifference;

			int years = totalMonths / MONTHS_IN_YEAR;

			int months = totalMonths - years * MONTHS_IN_YEAR;

			int days = spanFromCurrentMonth.Days;

			int hours = spanFromCurrentMonth.Hours;

			int minutes = spanFromCurrentMonth.Minutes;

			int seconds = spanFromCurrentMonth.Seconds;

			return new TimeInterval(years, months, days, hours, minutes, seconds);
		}
	}
}
